From 0444e5275d38b2e60753d0bad4321ac6d0bc5d3a Mon Sep 17 00:00:00 2001 From: "kaf24@firebug.cl.cam.ac.uk" Date: Tue, 8 Nov 2005 16:48:42 +0100 Subject: [PATCH] Fix alloc_skb() to ensure data is always physically contiguous. Signed-off-by: Keir Fraser --- linux-2.6-xen-sparse/arch/xen/Kconfig | 4 ++ .../arch/xen/configs/xen0_defconfig_x86_32 | 1 + .../arch/xen/configs/xen0_defconfig_x86_64 | 1 + .../arch/xen/configs/xenU_defconfig_x86_32 | 1 + .../arch/xen/configs/xenU_defconfig_x86_64 | 1 + .../arch/xen/configs/xen_defconfig_x86_32 | 1 + .../arch/xen/configs/xen_defconfig_x86_64 | 1 + linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c | 47 ++++++++++++++++++- linux-2.6-xen-sparse/net/core/skbuff.c | 2 + 9 files changed, 57 insertions(+), 2 deletions(-) diff --git a/linux-2.6-xen-sparse/arch/xen/Kconfig b/linux-2.6-xen-sparse/arch/xen/Kconfig index b03a8b0d7c..790c2d82e1 100644 --- a/linux-2.6-xen-sparse/arch/xen/Kconfig +++ b/linux-2.6-xen-sparse/arch/xen/Kconfig @@ -173,6 +173,10 @@ endchoice endmenu +config HAVE_ARCH_ALLOC_SKB + bool + default y + config HAVE_ARCH_DEV_ALLOC_SKB bool default y diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 index ef780d693a..bae115ecc7 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_32 @@ -25,6 +25,7 @@ CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_X86=y # CONFIG_XEN_X86_64 is not set +CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y # diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 index eea42fed6e..cb54da3b0e 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen0_defconfig_x86_64 @@ -25,6 +25,7 @@ CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_SCRUB_PAGES=y # CONFIG_XEN_X86 is not set CONFIG_XEN_X86_64=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y # diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 index 1e1c577008..0715a55361 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_32 @@ -22,6 +22,7 @@ CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_X86=y # CONFIG_XEN_X86_64 is not set +CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y # diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 index 1547c05a98..87ca4d45e1 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xenU_defconfig_x86_64 @@ -22,6 +22,7 @@ CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_SCRUB_PAGES=y # CONFIG_XEN_X86 is not set CONFIG_XEN_X86_64=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y # diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 index 63e1d4cc9c..d7e9af6b78 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_32 @@ -25,6 +25,7 @@ CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_SCRUB_PAGES=y CONFIG_XEN_X86=y # CONFIG_XEN_X86_64 is not set +CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y # diff --git a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 index 10dcc41c04..4a14a2d9ba 100644 --- a/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 +++ b/linux-2.6-xen-sparse/arch/xen/configs/xen_defconfig_x86_64 @@ -25,6 +25,7 @@ CONFIG_XEN_NETDEV_FRONTEND=y CONFIG_XEN_SCRUB_PAGES=y # CONFIG_XEN_X86 is not set CONFIG_XEN_X86_64=y +CONFIG_HAVE_ARCH_ALLOC_SKB=y CONFIG_HAVE_ARCH_DEV_ALLOC_SKB=y # diff --git a/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c b/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c index 1a1d113186..e1cd013e24 100644 --- a/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c +++ b/linux-2.6-xen-sparse/arch/xen/kernel/skbuff.c @@ -20,6 +20,37 @@ #define MAX_SKBUFF_ORDER 2 static kmem_cache_t *skbuff_order_cachep[MAX_SKBUFF_ORDER + 1]; +static struct { + int size; + kmem_cache_t *cachep; +} skbuff_small[] = { { 512, NULL }, { 2048, NULL } }; + +struct sk_buff *alloc_skb(unsigned int length, int gfp_mask) +{ + int order, i; + kmem_cache_t *cachep; + + length = SKB_DATA_ALIGN(length) + sizeof(struct skb_shared_info); + + if (length <= skbuff_small[ARRAY_SIZE(skbuff_small)-1].size) { + for (i = 0; skbuff_small[i].size < length; i++) + continue; + cachep = skbuff_small[i].cachep; + } else { + order = get_order(length); + if (order > MAX_SKBUFF_ORDER) { + printk(KERN_ALERT "Attempt to allocate order %d " + "skbuff. Increase MAX_SKBUFF_ORDER.\n", order); + return NULL; + } + cachep = skbuff_order_cachep[order]; + } + + length -= sizeof(struct skb_shared_info); + + return alloc_skb_from_cache(cachep, length, gfp_mask); +} + struct sk_buff *__dev_alloc_skb(unsigned int length, int gfp_mask) { struct sk_buff *skb; @@ -68,8 +99,20 @@ static void skbuff_dtor(void *buf, kmem_cache_t *cachep, unsigned long unused) static int __init skbuff_init(void) { static char name[MAX_SKBUFF_ORDER + 1][20]; + static char small_name[ARRAY_SIZE(skbuff_small)][20]; unsigned long size; - int order; + int i, order; + + for (i = 0; i < ARRAY_SIZE(skbuff_small); i++) { + size = skbuff_small[i].size; + sprintf(small_name[i], "xen-skb-%lu", size); + /* + * No ctor/dtor: objects do not span page boundaries, and they + * are only used on transmit path so no need for scrubbing. + */ + skbuff_small[i].cachep = kmem_cache_create( + small_name[i], size, size, 0, NULL, NULL); + } for (order = 0; order <= MAX_SKBUFF_ORDER; order++) { size = PAGE_SIZE << order; @@ -82,7 +125,7 @@ static int __init skbuff_init(void) return 0; } -__initcall(skbuff_init); +core_initcall(skbuff_init); EXPORT_SYMBOL(__dev_alloc_skb); diff --git a/linux-2.6-xen-sparse/net/core/skbuff.c b/linux-2.6-xen-sparse/net/core/skbuff.c index 9e144aa414..5f7d3503c4 100644 --- a/linux-2.6-xen-sparse/net/core/skbuff.c +++ b/linux-2.6-xen-sparse/net/core/skbuff.c @@ -129,6 +129,7 @@ void skb_under_panic(struct sk_buff *skb, int sz, void *here) * Buffers may only be allocated from interrupts using a @gfp_mask of * %GFP_ATOMIC. */ +#ifndef CONFIG_HAVE_ARCH_ALLOC_SKB struct sk_buff *alloc_skb(unsigned int size, int gfp_mask) { struct sk_buff *skb; @@ -166,6 +167,7 @@ nodata: skb = NULL; goto out; } +#endif /* !CONFIG_HAVE_ARCH_ALLOC_SKB */ /** * alloc_skb_from_cache - allocate a network buffer -- 2.30.2